var LoadedData = {};
var ContainersByDataId = {};

!function ($) {
    var FilterDataService = function (options) {
        if (options) _.extend(this, options);
    };

    FilterDataService.prototype = {
        constructor:FilterDataService,

        fetch: function(dataurl, callback) {
            var ordered_genes = $("#gene_list").ordered_list();
            var stopProgressFn = $("#progress").progressbar({ "urlForText": dataurl });
            $.ajax({
                "url":this.service,
                "data":{ filepath:dataurl, genes:ordered_genes.join(",") },
                "context": this,
                "success":function (txt) {
                    var data = this._parse(ordered_genes, txt);
                    callback({ "id":dataurl, "data": data });
                },
                "complete": stopProgressFn
            });
        },

        _parse: function(ordered_genes, txt) {
            var lines = txt.split("\n");
            var samples = lines[0].split("\t");

            var visdata = {};
            _.each(_.rest(lines, 1), function(line) {
                var valuelines = line.split("\t");
                var gene = valuelines[0];
                if (gene) {
                    gene = gene.trim();
                    if (ordered_genes.indexOf(gene) >= 0) {
                        var mutatedPatients = MutatedPatientsByGene[gene];
                        _.each(_.rest(valuelines, 3), function(value, idx) {
                            var sample = samples[idx + 3];
                            var sampleData = visdata[sample];
                            if (!sampleData) {
                                sampleData = {};
                                visdata[sample] = sampleData;
                            }
                            var isMutated = (mutatedPatients && (mutatedPatients.indexOf(sample.substring(0, 12)) >= 0));
                            var label = sample + "\n" + gene + "\n" + value;
                            if (isMutated) label += "\nMutation";
                            sampleData[gene] = { "value":parseFloat(value), "isMutated":isMutated, "label":label };
                        });
                    }
                }
            });
            return visdata;
        }
    };

    $.fn.filter_data_service = function (options) {
        var ft;
        this.each(function () {
            var $this = $(this);
            ft = $this.data("FilterDataService");
            if (!ft) {
                $this.data("FilterDataService", (ft = new FilterDataService(options)));
            }
        });
        return ft;
    };


}(window.jQuery);

//Data Calls
var ReloadData = function () {
    var loadedDataUrls = _.map(LoadedData, function(data,url){ return url; });
    LoadedData = {};
    _.each(loadedDataUrls, Visualize);
};

//Visualization Controls
var Visualize = function (url) {
    var existingdata = LoadedData[url];
    if (existingdata) {
        UpdateVisualization();
        ShowVisTab(url);
        return;
    }

    $(window).filter_data_service().fetch(url, function (visdata) {
        LoadedData[visdata.id] = visdata;
        CreateVisualizationTab(visdata);
        DisplayVisualization(visdata);
    });
};

var CreateVisualizationTab = function(visdata) {
    var containerId = ShowVisTab(visdata.id);
    if (containerId) {
        return;
    }

    containerId = ("vis_" + Math.random()).replace(".", "");
    ContainersByDataId[visdata.id] = containerId;

    var visdatalabel= visdata.id;
    if (visdatalabel.indexOf("/") >= 0) {
        visdatalabel = visdatalabel.substring(visdatalabel.lastIndexOf("/") + 1);
    }

    $("#data_vis").append("<div id='" + containerId + "' class='tab-pane'></div>");
    $("#data_vis_tabs").append("<li><a href='#" + containerId + "' title='" + visdata.id + "'>" + visdatalabel + "</a></li>");
    $('#data_vis_tabs a[href="#' + containerId + '"]').click(function (e) {
        e.preventDefault();
        $(this).tab("show");
    });
    $('#data_vis_tabs a[href="#' + containerId + '"]').tab('show');
};

var ShowVisTab = function(url) {
    var containerId = ContainersByDataId[url];
    if (containerId) {
        $('#data_vis_tabs a[href="#' + containerId + '"]').tab('show');
    }
    return containerId;
};

var DisplayVisualization = function (visdata) {
    console.log("DisplayVisualization(" + visdata.id + ")");

    var cluster_labels = $("#cluster_list").ordered_list();
    var row_labels = $("#gene_list").ordered_list();
    console.log("DisplayVisualization(" + visdata.id + "):" + row_labels);
    var columns_by_cluster = GetSortedSamplesByCluster(visdata.data);
    var color_fn = GetRangeColorsFn();

    if (_.isEmpty(cluster_labels)) cluster_labels = _.keys(columns_by_cluster);

    var optns = {
        bar_width:4,
        column_spacing:1,
        plot_width:3000,
        label_width:70,
        highlight_cls:"mutation",
        color_fn:color_fn,
        columns_by_cluster:columns_by_cluster,
        cluster_labels:cluster_labels,
        row_labels:row_labels
    };

    _.extend(optns, { "bar_height": $("#slider_barheight").oncovis_range_value() });
    _.extend(optns, { "row_spacing": $("#slider_rowspacing").oncovis_range_value() });
    _.extend(optns, { "bar_width": $("#slider_barwidth").oncovis_range_value() });
    _.extend(optns, { "column_spacing": $("#slider_barspacing").oncovis_range_value() });
    _.extend(optns, { "cluster_spacing": $("#slider_clusterspacing").oncovis_range_value() });
    _.extend(optns, { "label_fontsize": $("#slider_fontsize").oncovis_range_value() });

    $("#" + ContainersByDataId[visdata.id]).oncovis(visdata.data, optns);
};

var UpdateVisualization = function () {
    var cluster_labels = $("#cluster_list").ordered_list();
    var row_labels = $("#gene_list").ordered_list();
    var color_fn = GetRangeColorsFn();

    _.each(LoadedData, function (visdata) {
        var viscontainer = $("#" + ContainersByDataId[visdata.id]);
        viscontainer.update({ "cluster_labels": cluster_labels, "row_labels": row_labels, "color_fn":color_fn });
        _.each(GetSortedSamplesByCluster(visdata.data), function (sorted_samples, cluster_id) {
            viscontainer.updateClusterColumns(cluster_id, sorted_samples);
        });
    });
};

//Domain Functions
var GetSortedSamplesByCluster = function (visdata) {
    var cluster_data = {};
    var clusterByPatient = {};
    _.each(PatientsByCluster, function (patients, cluster) {
        cluster_data[cluster] = [];
        _.each(patients, function (patient) {
            clusterByPatient[patient] = cluster;
        });
    });

    _.each(visdata, function (ref_data, sample_id) {
        var found_cluster = clusterByPatient[sample_id.substring(0, 12)];
        if (_.isEmpty(found_cluster)) found_cluster = "NA";
        if (_.isEmpty(cluster_data[found_cluster])) cluster_data[found_cluster] = [];
        cluster_data[found_cluster].push({"id":sample_id, "ref":ref_data});
    });

    var orderedGeneList = $("#gene_list").ordered_list();
    var discretizeFn = GetDiscreteValuesFn();
    var discretizedSortFn = function (a, b) {
        if (a && b) {
            var diff = false;
            _.each(orderedGeneList, function (orderedGene) {
                if (diff !== false) return;

                var itemA = a["ref"][orderedGene];
                var itemB = b["ref"][orderedGene];
                if (itemA && itemB) {
                    var discreteA = discretizeFn(itemA.value);
                    var discreteB = discretizeFn(itemB.value);
                    if (discreteA != discreteB) {
                        diff = discreteA - discreteB;
                    } else {
                        if (itemA.isMutated && !itemB.isMutated) diff = -1;
                        if (!itemA.isMutated && itemB.isMutated) diff = 1;
                    }
                }
            });

            if (diff) return diff;

            var firstGene = orderedGeneList[0];
            var itemA = a["ref"][firstGene];
            var itemB = b["ref"][firstGene];
            if (itemA && itemB) {
                return itemA.value - itemB.value
            }
        }
        return 0;
    };

    var sorted_samples_by_cluster = {};
    _.each(cluster_data, function (unsorted_samples, cluster_id) {
        var sorted_samples = unsorted_samples.sort(discretizedSortFn);
        var sorted_sample_ids = [];
        _.each(sorted_samples, function (sorted_sample) {
            sorted_sample_ids.push(sorted_sample.id);
        });
        sorted_samples_by_cluster[cluster_id] = sorted_sample_ids;
    });
    return sorted_samples_by_cluster;
};

var GetDiscreteValuesFn = function () {
    var homoz_del = $("#slider_A").datarange_calculated();
    var hetez_del = $("#slider_B").datarange_calculated();
    var diploid = $("#slider_C").datarange_calculated();
    var gain = $("#slider_D").datarange_calculated();

    return function (val) {
        if (val < homoz_del) return 5;
        if (val < hetez_del) return 4;
        if (val < diploid) return 3;
        if (val < gain) return 2;
        return 1;
    };
};

var GetRangeColorsFn = function () {
    var homoz_del = $("#slider_A").datarange_calculated();
    var hetez_del = $("#slider_B").datarange_calculated();
    var diploid = $("#slider_C").datarange_calculated();
    var gain = $("#slider_D").datarange_calculated();

    return function (val) {
        if (val < homoz_del) return "homoz_del";
        if (val < hetez_del) return "hetez_del";
        if (val < diploid) return "diploid";
        if (val < gain) return "gain";
        return "amplification";
    };
};

